/*
+------------------------------------------------------------------------------
|
| FILENAME: cairo.i
|
| PROJECT: Cairo Libraries
|
| FILE DESCRIPTION:
|    This is a SWIG script used to generate an access library for SWIG
|    for various scripting languages.
|
+------------------------------------------------------------------------------
|
| Cairolib is a series of extensions, examples, and libraries for the
| Cairo graphics package (see http://www.cairographics.org).
| 
| Copyright (C) 2006  Bradford Elliott
|
| This library is free software; you can redistribute it and/or
| modify it under the terms of the GNU Lesser General Public
| License as published by the Free Software Foundation; either
| version 2.1 of the License, or (at your option) any later version.
| 
| This library is distributed in the hope that it will be useful,
| but WITHOUT ANY WARRANTY; without even the implied warranty of
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
| Lesser General Public License for more details.
| 
| You should have received a copy of the GNU Lesser General Public
| License along with this library; if not, write to the Free Software
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
| 
+------------------------------------------------------------------------------
*/
%module cairolib
%{
    #include "cairo.h"
    #define min(a,b) (((a)<(b))?(a):(b))
    
    class cairolib_t
    {
    public:
        cairolib_t(int width, int height)
        {
            m_cairo_surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
            m_cairo_image   = cairo_create(m_cairo_surface);
            cairo_set_source_rgb(m_cairo_image, 1, 1, 1);
            cairo_rectangle(m_cairo_image, 0, 0, width, height);
            cairo_fill(m_cairo_image);
        }
        
        void rectangle(double x, double y, double width, double height)
        {
            cairo_rectangle(m_cairo_image, x, y, width, height);
        }
        
        void ellipse(double x, double y, double width, double height)
        {
        }
        
        void write_to_png(const char* file, int width_destination, int height_destination)
        {
            int            width_source;
            int            height_source;
            unsigned char* data_source;
            unsigned char* data_destination;
            int            row;
    
            cairo_t* cr;
            cairo_surface_t* new_surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width_destination, height_destination);
            cr = cairo_create(new_surface);
            
            cairo_save(cr);
            cairo_set_source_surface(cr, m_cairo_surface, 0, 0);
            cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
            cairo_paint(cr);
            cairo_restore(cr);
            
            cairo_surface_write_to_png(new_surface, file);
        }
        
        void set_source_rgb(double red, double green, double blue)
        {
            cairo_set_source_rgb(m_cairo_image, red, green, blue);
        }
        
        void stroke(void)
        {
            cairo_stroke(m_cairo_image);
        }
        
        void fill(void)
        {
            cairo_fill(m_cairo_image);
        }
        
        void save(void)
        {
            cairo_save(m_cairo_image);
        }
        
        void restore(void)
        {
            cairo_restore(m_cairo_image);
        }
        
        void scale(double width, double height)
        {
            cairo_scale(m_cairo_image, width, height);
        }
        
        void translate(double x, double y)
        {
            cairo_translate(m_cairo_image, x, y);
        }
        
        void arc(double xc, double yc, double radius, double angle1, double angle2)
        {
            cairo_arc(m_cairo_image, xc, yc, radius, angle1, angle2);
        }
        
        void fill_preserve(void)
        {
            cairo_fill_preserve(m_cairo_image);
        }
        
        void show_text(const char* text)
        {
            cairo_show_text(m_cairo_image, text);
        }
        
        void set_font_size(double size)
        {
            cairo_set_font_size(m_cairo_image, size);
        }
        
        void text_extents(char *utf8,
                          int*        width,
                          int*        height)
        {
            cairo_text_extents_t extents;
            cairo_text_extents(m_cairo_image, utf8, &extents);
            
            *width = extents.width;
            *height = extents.height;
        }
                                             
        void line_to(double x, double y)
        {
            cairo_line_to(m_cairo_image, x, y);
        }
        
        void set_line_width(double width)
        {
            cairo_set_line_width(m_cairo_image, width);
        }
        
        double set_dash(double input_dashes[], int num_dashes, double offset)
        {
            cairo_set_dash(m_cairo_image, input_dashes, num_dashes, offset);
            
            return input_dashes[1];
        }
        
        void move_to(double x, double y)
        {
            cairo_move_to(m_cairo_image, x, y);
        }
        
        void curve_to(double x1, double y1, double x2,
                      double y2, double x3, double y3)
        {
            cairo_curve_to(m_cairo_image, x1, y1, x2, y2, x3, y3);
        }
        
        void new_path(void)
        {
            cairo_new_path(m_cairo_image);
        }
        
        void close_path(void)
        {
            cairo_close_path(m_cairo_image);
        }
        
    private:
        cairo_t*         m_cairo_image;
        cairo_surface_t* m_cairo_surface;
    };
%}

#include "cairo.h"
%include "typemaps.i"
%include "carrays.i"

%array_functions(double, doubleArray);

%apply int *OUTPUT { int *width };
%apply int *OUTPUT { int *height };
//%apply double *INPUT { double* input_dashes };


%typedef enum _cairo_format
{
    CAIRO_FORMAT_ARGB32,
    CAIRO_FORMAT_RGB24,
    CAIRO_FORMAT_A8,
    CAIRO_FORMAT_A1,
} cairo_format_t;

#define min(a,b) (((a)<(b))?(a):(b))

class cairolib_t{
    public:
        cairolib_t(int width, int height)
        {
            m_cairo_surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
            m_cairo_image = cairo_create(m_cairo_surface);
        }
        
        void rectangle(double x, double y, double width, double height)
        {
            cairo_rectangle(m_cairo_image, x, y, width, height);
        }
        
        void ellipse(double x, double y, double width, double height)
        {
            cairo_save(m_cairo_image);
            
            cairo_translate(m_cairo_image, x + width / 2., y + height / 2.);
            cairo_scale(m_cairo_image, 1. * (width / 2.), 1. * (height / 2.));
            cairo_arc(m_cairo_image, 0., 0., 1., 0., 2 * 3.1457);
            
            //self.SetupFill()
            //ctx.fill_preserve()
            //self.SetupStroke()
            //ctx.stroke()
            
            //ctx.restore();
        }
        
        void write_to_png(const char* file, int width_destination, int height_destination)
        {
            int            width_source;
            int            height_source;
            unsigned char* data_source;
            unsigned char* data_destination;
            int            row;
    
            cairo_surface_t* new_surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width_destination, height_destination);
            
            // Set the height/width of the surfaces
            height_source = cairo_image_surface_get_height(m_cairo_surface);
            width_source = cairo_image_surface_get_width(m_cairo_surface);
            
            // Get a pointer to the data of the original image surface
            data_source = cairo_image_surface_get_data(m_cairo_surface);
            data_destination = cairo_image_surface_get_data(new_surface);
            
            for(row = 0; row < min(height_source, height_destination); row++)
            {
                // If the source is wider than the destination surface then
                // only copy the source width amount for each row.
                if(width_source > width_destination)
                {
                    memcpy(data_destination + (row * width_destination * 4),
                           data_source + (row * width_source * 4), width_destination * 4);
                }
                else
                {
                    memcpy(data_destination + (row * width_destination * 4),
                           data_source + (row * width_source * 4), width_source * 4);
                }
            }
            
            // Flush the output surface since we've modified it
            cairo_surface_flush(new_surface);
            cairo_surface_write_to_png(new_surface, file);
        }
        
        void set_source_rgb(double red, double green, double blue)
        {
            cairo_set_source_rgb(m_cairo_image, red, green, blue);
        }
        
        void stroke(void)
        {
            cairo_stroke(m_cairo_image);
        }
        
        void fill(void)
        {
            cairo_fill(m_cairo_image);
        }
        
        void save(void)
        {
            cairo_save(m_cairo_image);
        }
        
        void restore(void)
        {
            cairo_restore(m_cairo_image);
        }
        
        void scale(double width, double height)
        {
            cairo_scale(m_cairo_image, width, height);
        }
        
        void translate(double x, double y)
        {
            cairo_translate(m_cairo_image, x, y);
        }
        
        void arc(double xc, double yc, double radius, double angle1, double angle2)
        {
            cairo_arc(m_cairo_image, xc, yc, radius, angle1, angle2);
        }
        
        void fill_preserve(void)
        {
            cairo_fill_preserve(m_cairo_image);
        }
            
        void show_text(const char* text)
        {
            cairo_show_text(m_cairo_image, text);
        }
        
        void set_font_size(double size)
        {
            cairo_set_font_size(m_cairo_image, size);
        }
        
        void text_extents(char *utf8,
                          int*        width,
                          int*        height)
        {
            cairo_text_extents_t extents;
            cairo_text_extents(m_cairo_image, utf8, &extents);
            
            *width = extents.width;
            *height = extents.height;
        }
        
        void line_to(double x, double y)
        {
            cairo_line_to(m_cairo_image, x, y);
        }
        
        void set_line_width(double width)
        {
            cairo_set_line_width(m_cairo_image, width);
        }
        
        double set_dash(double input_dashes[], int num_dashes, double offset)
        {
            cairo_set_dash(m_cairo_image, input_dashes, num_dashes, offset);
            
            return input_dashes[1];
        }
        
        void move_to(double x, double y)
        {
            cairo_move_to(m_cairo_image, x, y);
        }
        
        void curve_to(double x1, double y1, double x2,
                      double y2, double x3, double y3)
        {
            cairo_curve_to(m_cairo_image, x1, y1, x2, y2, x3, y3);
        }
        
        void new_path(void)
        {
            cairo_new_path(m_cairo_image);
        }
        
        void close_path(void)
        {
            cairo_close_path(m_cairo_image);
        }
    
    private:
        cairo_t*         m_cairo_image;
        cairo_surface_t* m_cairo_surface;
};
